#ifndef	lint
static const char rcsid[] = "$Id: receive.cpp 6 2004-09-18 20:02:00Z rushfan $" ;
#endif


#define	TEST	/* standalone test */

#include <unistd.h>
#include <string.h>
#include "zmodem.h"
#include <sys/stat.h>

#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/termios.h>
#include <sys/termio.h>		/* define TCSBRK */
#include <sys/param.h>

extern	int	errno ;

static	u_char	zeros[4] = {0,0,0,0} ;

main(argc,argv)
	int	argc ;
	char	**argv ;
{
	struct	termios	old_settings, new_settings ;
	fd_set	readfds ;
	struct timeval timeout ;
	int	i ;
	int	len ;
	char	buffer[1024] ;
	int	done = 0 ;
	int	filecount = 0 ;
	ZModem	info ;

#ifdef	TEST

static	u_char	Amsg0[] = {
	  0x72, 0x7a, 0x0d, 0x2a, 0x2a, 0x18, 0x42, 0x30, 
	  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 
	  0x30, 0x30, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x11, 
	} ;
static	u_char	Amsg1[] = {
	  0x2a, 0x18, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 
	  0x7d, 0xa4, 0xe2, 0xbc, 0x00, 0x18, 0x6b, 0x2f, 
	  0xaa, 0xb9, 0x9b, 0x2a, 0x18, 0x43, 0x02, 0x00, 
	  0x00, 0x00, 0x00, 0x7d, 0xa4, 0xe2, 0xbc, 
	} ;
static	u_char	Amsg2[] = {
	  0x00, 0x18, 0x6b, 0x2f, 0xaa, 0xb9, 0x9b, 0x2a, 
	  0x18, 0x43, 0x04, 0x00, 0x00, 0x04, 0x00, 0xd9, 
	  0x94, 0xce, 0x57, 
	} ;
static	u_char	Amsg3[] = {
	  0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2e, 
	  0x63, 0x00, 0x31, 0x36, 0x39, 0x38, 0x36, 0x20, 
	  0x35, 0x37, 0x30, 0x30, 0x36, 0x36, 0x37, 0x36, 
	  0x37, 0x30, 0x20, 0x31, 0x30, 0x30, 0x36, 0x36, 
	  0x34, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 
	  0x30, 0x00, 0x18, 0x6b, 0x57, 0xed, 0x76, 0xb6, 
	} ;
static	u_char	Amsg4[] = {
	  0x2a, 0x18, 0x43, 0x0a, 0x00, 0x00, 0x00, 0x00, 
	  0xbc, 0xef, 0x92, 0x8c, 0x0a, 0x23, 0x64, 0x65, 
	  0x66, 0x69, 0x6e, 0x65, 0x09, 0x54, 0x45, 0x53, 
	  0x54, 0x09, 0x2f, 0x2a, 0x20, 0x73, 0x74, 0x61, 
	  0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x20, 
	  0x74, 0x65, 0x73, 0x74, 0x20, 0x2a, 0x2f, 0x0a, 
	  0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 
	  0x65, 0x20, 0x3c, 0x75, 0x6e, 0x69, 0x73, 0x74, 
	  0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x23, 0x69, 0x6e, 
	  0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 
	  0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x3e, 
	  0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 
	  0x65, 0x20, 0x22, 0x7a, 0x6d, 0x6f, 0x64, 0x65, 
	  0x6d, 0x2e, 0x68, 0x22, 0x0a, 0x23, 0x69, 0x6e, 
	  0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 
	  0x79, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x2e, 
	  0x68, 0x3e, 0x0a, 0x0a, 0x23, 0x69, 0x6e, 0x63, 
	  0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x66, 0x63, 
	  0x6e, 0x74, 0x6c, 0x2e, 0x68, 0x3e, 0x0a, 0x23, 
	  0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 
	  0x3c, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x2e, 0x68, 
	  0x3e, 0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 
	  0x64, 0x65, 0x20, 0x3c, 0x73, 0x79, 0x73, 0x2f, 
	  0x74, 0x69, 0x6d, 0x65, 0x2e, 0x68, 0x3e, 0x0a, 
	  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 
	  0x20, 0x3c, 0x73, 0x79, 0x73, 0x2f, 0x74, 0x65, 
	  0x72, 0x6d, 0x69, 0x6f, 0x73, 0x2e, 0x68, 0x3e, 
	  0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 
	  0x65, 0x20, 0x3c, 0x73, 0x79, 0x73, 0x2f, 0x74, 
	  0x65, 0x72, 0x6d, 0x69, 0x6f, 0x2e, 0x68, 0x3e, 
	  0x09, 0x09, 0x2f, 0x2a, 0x20, 0x64, 0x65, 0x66, 
	  0x69, 0x6e, 0x65, 0x20, 0x54, 0x43, 0x53, 0x42, 
	  0x52, 0x4b, 0x20, 0x2a, 0x2f, 0x0a, 0x23, 0x69, 
	  0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 
	  0x73, 0x79, 0x73, 0x2f, 0x70, 0x61, 0x72, 0x61, 
	  0x6d, 0x2e, 0x68, 0x3e, 0x0a, 0x0a, 0x65, 0x78, 
	  0x74, 0x65, 0x72, 0x6e, 0x09, 0x69, 0x6e, 0x74, 
	  0x09, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x20, 0x3b, 
	  0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 
	  0x09, 0x75, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x09, 
	  0x7a, 0x65, 0x72, 0x6f, 0x73, 0x5b, 0x34, 0x5d, 
	  0x20, 0x3d, 0x20, 0x7b, 0x30, 0x2c, 0x30, 0x2c, 
	  0x30, 0x2c, 0x30, 0x7d, 0x20, 0x3b, 0x0a, 0x0a, 
	  0x6d, 0x61, 0x69, 0x6e, 0x28, 0x61, 0x72, 0x67, 
	  0x63, 0x2c, 0x61, 0x72, 0x67, 0x76, 0x29, 0x0a, 
	  0x09, 0x69, 0x6e, 0x74, 0x09, 0x61, 0x72, 0x67, 
	  0x63, 0x20, 0x3b, 0x0a, 0x09, 0x63, 0x68, 0x61, 
	  0x72, 0x09, 0x2a, 0x2a, 0x61, 0x72, 0x67, 0x76, 
	  0x20, 0x3b, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 
	  0x72, 0x75, 0x63, 0x74, 0x09, 0x74, 0x65, 0x72, 
	  0x6d, 0x69, 0x6f, 0x73, 0x09, 0x6f, 0x6c, 0x64, 
	  0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 
	  0x73, 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x5f, 0x73, 
	  0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 
	  0x3b, 0x0a, 0x09, 0x66, 0x64, 0x5f, 0x73, 0x65, 
	  0x74, 0x09, 0x72, 0x65, 0x61, 0x64, 0x66, 0x64, 
	  0x73, 0x20, 0x3b, 0x0a, 0x09, 0x73, 0x74, 0x72, 
	  0x75, 0x63, 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65, 
	  0x76, 0x61, 0x6c, 0x20, 0x74, 0x69, 0x6d, 0x65, 
	  0x6f, 0x75, 0x74, 0x20, 0x3b, 0x0a, 0x09, 0x69, 
	  0x6e, 0x74, 0x09, 0x69, 0x20, 0x3b, 0x0a, 0x09, 
	  0x69, 0x6e, 0x74, 0x09, 0x6c, 0x65, 0x6e, 0x20, 
	  0x3b, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x09, 
	  0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5b, 0x31, 
	  0x30, 0x32, 0x34, 0x5d, 0x20, 0x3b, 0x0a, 0x09, 
	  0x69, 0x6e, 0x74, 0x09, 0x64, 0x6f, 0x6e, 0x65, 
	  0x20, 0x3d, 0x20, 0x30, 0x20, 0x3b, 0x0a, 0x09, 
	  0x69, 0x6e, 0x74, 0x09, 0x66, 0x69, 0x6c, 0x65, 
	  0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d, 0x20, 
	  0x30, 0x20, 0x3b, 0x0a, 0x09, 0x5a, 0x4d, 0x6f, 
	  0x64, 0x65, 0x6d, 0x09, 0x69, 0x6e, 0x66, 0x6f, 
	  0x20, 0x3b, 0x0a, 0x0a, 0x23, 0x69, 0x66, 0x64, 
	  0x65, 0x66, 0x09, 0x54, 0x45, 0x53, 0x54, 0x0a, 
	  0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x09, 
	  0x75, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x09, 0x41, 
	  0x6d, 0x73, 0x67, 0x30, 0x5b, 0x5d, 0x20, 0x3d, 
	  0x20, 0x7b, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 
	  0x37, 0x32, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x61, 
	  0x2c, 0x20, 0x30, 0x78, 0x30, 0x64, 0x2c, 0x20, 
	  0x30, 0x78, 0x32, 0x61, 0x2c, 0x20, 0x30, 0x78, 
	  0x32, 0x61, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x38, 
	  0x2c, 0x20, 0x30, 0x78, 0x34, 0x32, 0x2c, 0x20, 
	  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x0a, 0x09, 
	  0x20, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 
	  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 
	  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 
	  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 
	  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 
	  0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 
	  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 
	  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 
	  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x64, 
	  0x2c, 0x20, 0x30, 0x78, 0x30, 0x61, 0x2c, 0x20, 
	  0x30, 0x78, 0x31, 0x31, 0x2c, 0x20, 0x0a, 0x09, 
	  0x7d, 0x20, 0x3b, 0x0a, 0x73, 0x74, 0x61, 0x74, 
	  0x69, 0x63, 0x09, 0x75, 0x5f, 0x63, 0x68, 0x61, 
	  0x72, 0x09, 0x41, 0x6d, 0x73, 0x67, 0x31, 0x5b, 
	  0x5d, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x20, 
	  0x20, 0x30, 0x78, 0x32, 0x61, 0x2c, 0x20, 0x30, 
	  0x78, 0x31, 0x38, 0x2c, 0x20, 0x30, 0x78, 0x34, 
	  0x33, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x34, 0x2c, 
	  0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 
	  0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 
	  0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 
	  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x64, 
	  0x64, 0x2c, 0x20, 0x30, 0x78, 0x35, 0x31, 0x2c, 
	  0x20, 0x30, 0x78, 0x61, 0x32, 0x2c, 0x20, 0x30, 
	  0x78, 0x33, 0x33, 0x2c, 0x20, 0x30, 0x78, 0x37, 
	  0x35, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x34, 0x2c, 
	  0x20, 0x30, 0x78, 0x36, 0x39, 0x2c, 0x20, 0x30, 
	  0x78, 0x36, 0x63, 0x2c, 0x20, 0x0a, 0x09, 0x20, 
	  0x20, 0x30, 0x78, 0x37, 0x33, 0x2c, 0x20, 0x30, 
	  0x78, 0x32, 0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 
	  0x33, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 
	  0x20, 0x30, 0x78, 0x33, 0x31, 0x2c, 0x20, 0x30, 
	  0x78, 0x33, 0x31, 0x2c, 0x20, 0x30, 0x78, 0x33, 
	  0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x37, 0x2c, 
	  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32, 
	  0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x35, 0x2c, 
	  0x20, 0x30, 0x78, 0x33, 0x37, 0x2c, 0x20, 0x30, 
	  0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 
	  0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 
	  0x20, 0x30, 0x78, 0x33, 0x35, 0x2c, 0x20, 0x30, 
	  0x78, 0x33, 0x36, 0x2c, 0x20, 0x0a, 0x09, 0x20, 
	  0x20, 0x30, 0x78, 0x33, 0x31, 0x2c, 0x20, 0x30, 
	  0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 
	  0x34, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30, 0x2c, 
	  0x20, 0x30, 0x78, 0x33, 0x18, 0x6a, 0xf8, 0x0e, 
	  0xd1, 0x2f, 0x31, 0x2c, 0x20, 0x30, 0x78, 0x33, 
	  0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 
	  0x20, 0x30, 0x78, 0x33, 0x36, 0x2c, 0x20, 0x0a, 
	  0x09, 0x20, 0x20, 0x30, 0x78, 0x33, 0x36, 0x2c, 
	  0x20, 0x30, 0x78, 0x33, 0x34, 0x2c, 0x20, 0x30, 
	  0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 
	  0x30, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30, 0x2c, 
	  0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 
	  0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 
	  0x30, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 
	  0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 
	  0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 
	  0x20, 0x30, 0x78, 0x31, 0x38, 0x2c, 0x20, 0x30, 
	  0x78, 0x36, 0x62, 0x2c, 0x20, 0x30, 0x78, 0x63, 
	  0x63, 0x2c, 0x20, 0x30, 0x78, 0x38, 0x38, 0x2c, 
	  0x20, 0x30, 0x78, 0x38, 0x36, 0x2c, 0x20, 0x0a, 
	  0x09, 0x20, 0x20, 0x30, 0x78, 0x31, 0x61, 0x2c, 
	  0x20, 0x0a, 0x09, 0x7d, 0x20, 0x3b, 0x0a, 0x73, 
	  0x74, 0x61, 0x74, 0x69, 0x63, 0x09, 0x75, 0x5f, 
	  0x63, 0x68, 0x61, 0x72, 0x09, 0x41, 0x6d, 0x73, 
	  0x67, 0x32, 0x5b, 0x5d, 0x20, 0x3d, 0x20, 0x7b, 
	  0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32, 0x61, 
	  0x2c, 0x20, 0x30, 0x78, 0x31, 0x38, 0x2c, 0x20, 
	  0x30, 0x78, 0x34, 0x33, 0x2c, 0x20, 0x30, 0x78, 
	  0x30, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 
	  0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 
	  0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 
	  0x30, 0x30, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, 
	  0x30, 0x78, 0x64, 0x64, 0x2c, 0x20, 0x30, 0x78, 
	  0x35, 0x31, 0x2c, 0x20, 0x30, 0x78, 0x61, 0x32, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x33, 0x2c, 0x20, 
	  0x30, 0x78, 0x37, 0x35, 0x2c, 0x20, 0x30, 0x78, 
	  0x37, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x39, 
	  0x2c, 0x20, 0x30, 0x78, 0x36, 0x63, 0x2c, 0x20, 
	  0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x37, 0x33, 
	  0x2c, 0x20, 0x30, 0x78, 0x32, 0x65, 0x2c, 0x20, 
	  0x30, 0x78, 0x36, 0x33, 0x2c, 0x20, 0x30, 0x78, 
	  0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x31, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x31, 0x2c, 0x20, 
	  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 
	  0x33, 0x37, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, 
	  0x30, 0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 
	  0x33, 0x35, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x37, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 
	  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 
	  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x35, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x36, 0x2c, 0x20, 
	  0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x33, 0x31, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 
	  0x30, 0x78, 0x33, 0x34, 0x2c, 0x20, 0x30, 0x78, 
	  0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x31, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 
	  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 
	  0x33, 0x36, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, 
	  0x30, 0x78, 0x33, 0x36, 0x2c, 0x20, 0x30, 0x78, 
	  0x33, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 
	  0x30, 0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 
	  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 
	  0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32, 0x30, 
	  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 
	  0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 
	  0x31, 0x38, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x62, 
	  0x2c, 0x20, 0x30, 0x78, 0x63, 0x63, 0x2c, 0x20, 
	  0x30, 0x78, 0x38, 0x38, 0x2c, 0x20, 0x30, 0x78, 
	  0x38, 0x36, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, 
	  0x30, 0x78, 0x31, 0x61, 0x2c, 0x20, 0x0a, 0x09, 
	  0x7d, 0x20, 0x3b, 0x0a, 0x73, 0x74, 0x61, 0x74, 
	  0x69, 0x63, 0x09, 0x75, 0x5f, 0x63, 0x68, 0x61, 
	  0x72, 0x09, 0x41, 0x6d, 0x73, 0x67, 0x33, 0x5b, 
	  0x5d, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x20, 
	  0x20, 0x30, 0x78, 0x32, 0x61, 0x2c, 0x20, 0x30, 
	  0x78, 0x31, 0x38, 0x2c, 0x20, 0x30, 0x78, 0x34, 
	  0x33, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x61, 0x2c, 
	  0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 
	  0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 
	  0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 
	  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x62, 
	  0x63, 0x2c, 0x20, 0x30, 0x78, 0x65, 0x66, 0x2c, 
	  0x20, 0x30, 0x78, 0x39, 0x32, 0x2c, 0x20, 0x30, 
	  0x78, 0x38, 0x63, 0x2c, 0x20, 0x30, 0x78, 0x30, 
	  0x61, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x2c, 
	  0x20, 0x30, 0x78, 0x36, 0x39, 0x2c, 0x20, 0x30, 
	  0x78, 0x36, 0x65, 0x2c, 0x20, 0x0a, 0x09, 0x20, 
	  0x20, 0x30, 0x78, 0x36, 0x33, 0x2c, 0x20, 0x30, 
	  0x78, 0x36, 0x63, 0x2c, 0x20, 0x30, 0x78, 0x37, 
	  0x35, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x34, 0x2c, 
	  0x20, 0x30, 0x78, 0x36, 0x35, 0x2c, 0x20, 0x30, 
	  0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 
	  0x63, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x33, 0x2c, 
	  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x37, 
	  0x39, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x33, 0x2c, 
	  0x20, 0x30, 0x78, 0x32, 0x66, 0x2c, 0x20, 0x30, 
	  0x78, 0x37, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x36, 
	  0x35, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x32, 0x2c, 
	  0x20, 0x30, 0x78, 0x36, 0x64, 0x2c, 0x20, 0x30, 
	  0x78, 0x36, 0x39, 0x2c, 0x20, 0x0a, 0x09, 0x20, 
	  0x20, 0x30, 0x78, 0x36, 0x66, 0x2c, 0x20, 0x30, 
	  0x78, 0x37, 0x33, 0x2c, 0x20, 0x30, 0x78, 0x32, 
	  0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x38, 0x2c, 
	  0x20, 0x30, 0x78, 0x33, 0x65, 0x2c, 0x20, 0x30, 
	  0x78, 0x30, 0x61, 0x2c, 0x20, 0x30, 0x78, 0x32, 
	  0x33, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x39, 0x2c, 
	  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x36, 
	  0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x33, 0x2c, 
	  0x20, 0x30, 0x78, 0x36, 0x63, 0x2c, 0x20, 0x30, 
	  0x78, 0x37, 0x35, 0x2c, 0x20, 0x30, 0x78, 0x36, 
	  0x34, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x35, 0x2c, 
	  0x20, 0x30, 0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 
	  0x78, 0x32, 0x32, 0x2c, 0x20, 0x0a, 0x09, 0x20, 
	  0x20, 0x30, 0x78, 0x37, 0x38, 0x2c, 0x20, 0x30, 
	  0x78, 0x36, 0x64, 0x2c, 0x20, 0x30, 0x78, 0x36, 
	  0x66, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x34, 0x2c, 
	  0x20, 0x30, 0x78, 0x36, 0x35, 0x2c, 0x20, 0x30, 
	  0x78, 0x36, 0x64, 0x2c, 0x20, 0x30, 0x78, 0x32, 
	  0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x38, 0x2c, 
	  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32, 
	  0x32, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x61, 0x2c, 
	  0x20, 0x30, 0x78, 0x30, 0x61, 0x2c, 0x20, 0x30, 
	  0x78, 0x30, 0x61, 0x2c, 0x20, 0x30, 0x78, 0x36, 
	  0x39, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x65, 0x2c, 
	  0x20, 0x30, 0x78, 0x37, 0x34, 0x2c, 0x20, 0x30, 
	  0x78, 0x30, 0x61, 0x2c, 0x20, 0x0a, 0x09, 0x20, 
	  0x20, 0x30, 0x78, 0x37, 0x33, 0x2c, 0x20, 0x30, 
	  0x78, 0x36, 0x35, 0x2c, 0x20, 0x30, 0x78, 0x36, 
	  0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x34, 0x2c, 
	  0x20, 0x30, 0x78, 0x34, 0x33, 0x2c, 0x20, 0x30, 
	  0x78, 0x36, 0x18, 0x6a, 0x4a, 0xe5, 0x72, 0x71, 
	} ;

#define	E(b)	{b, sizeof(b)}
static	struct {u_char *am; int len} Amsgs[] = {
	  E(Amsg0),
	  E(Amsg1),
	  E(Amsg2),
	  E(Amsg3),
	  E(Amsg4),} ;

#endif	/* TEST */

	/* try to trap uninit. variables */
	memset(&info,0xa5,sizeof(info)) ;

	info.zrinitflags = CANFDX|CANOVIO|CANBRK|CANFC32 ;
	info.packetsize = 128 ;
	info.bufsize = 0 ;

#ifdef	TEST
	done = ZmodemRInit(&info) ;
	for(i=0; !done; ++i )
	  done = ZmodemRcv(Amsgs[i].am, Amsgs[i].len, &info) ;

#else
	if( argc < 2 )
	  exit(2) ;

	info.ifd = open(argv[1], O_RDWR) ;

	if( info.ifd == -1 )
	  exit(1) ;

	tcgetattr(info.ifd,&old_settings) ;
	new_settings = old_settings ;

	new_settings.c_iflag &=
	  ~(ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXOFF|IMAXBEL) ;
	new_settings.c_oflag = 0 ;
	new_settings.c_cflag = B300|CS8|CREAD|CLOCAL ;
	new_settings.c_lflag = 0 ;
	new_settings.c_cc[VMIN] = 32 ;
	new_settings.c_cc[VTIME] = 1 ;
	tcsetattr(info.ifd,TCSADRAIN, &new_settings) ;

	done = ZmodemRInit(&info) ;

	while(!done)
	{
	  FD_ZERO(&readfds) ;
	  FD_SET(info.ifd, &readfds) ;
	  timeout.tv_sec = info.timeout ;
	  timeout.tv_usec = 0 ;
	  i = select(info.ifd+1, &readfds,NULL,NULL, &timeout) ;
	  if( i<0 )
	    perror("select") ;
	  else if( i==0 )
	    done = ZmodemTimeout(&info) ;
	  else {
	    len = read(info.ifd, buffer, sizeof(buffer)) ;
	    done = ZmodemRcv(buffer, len, &info) ;
	  }
	}

	tcsetattr(info.ifd,TCSADRAIN, &old_settings) ;
#endif	/* TEST */
	exit(0) ;
}




int
ZXmitStr(buffer, len, info)
	u_char	*buffer ;
	int	len ;
	ZModem	*info ;
{
	int	i,j ;
	u_char	c ;
extern	double	drand48() ;

#ifdef	TEST
	for(i=0; i<len; i += 16)
	{
	  printf("   ") ;
	  for(j=0; j<16 && i+j<len; ++j)
	    printf("%2.2x ", buffer[i+j]) ;
	  for(; j<16; ++j)
	    printf("   ") ;
	  printf("  |") ;
	  for(j=0; j<16 && i+j<len; ++j)
	    putchar(((c=buffer[i+j]) < 040 || c >= 0177) ? '.' : c ) ;
	  printf("|\n") ;
	}
#else

#ifdef	COMMENT
/* TEST: randomly corrupt one out of every 300 bytes */
for(i=0; i<len; ++i)
  if( drand48() < 1./300. ) {
    fprintf(stderr, "byte %d was %2.2x, is", i, buffer[i]) ;
    buffer[i] ^= 1<<(lrand48()&7) ;
    fprintf(stderr, " %2.2x\n", buffer[i]) ;
  }
#endif	/* COMMENT */

	if( write(info->ifd, buffer, len) != len )
	  return ZmErrSys ;
#endif	/* TEST */

	return 0 ;
}


void
ZIFlush(info)
	ZModem	*info ;
{
}

void
ZOFlush(info)
	ZModem	*info ;
{
}

void
ZStatus(i,j,str)
{
	fprintf(stderr,"status %d=%d\n",i,j) ;
}


int
ZAttn(info)
	ZModem	*info ;
{
	char	*ptr ;
	int	i = 0 ;

	for(ptr = info->attn; *ptr != '\0'; ++ptr) {
	  if( *ptr == ATTNBRK )
	    ioctl(info->ifd, TCSBRK, 0) ;
	  else if( *ptr == ATTNPSE )
	    sleep(1) ;
	  else
	    write(info->ifd, ptr, 1) ;
	}
	return 0 ;
}


FILE *
ZOpenFile(name, crc, info)
	char	*name ;
	u_long	crc ;
	ZModem	*info ;
{
	struct stat	buf ;
	int		exists ;	/* file already exists */
static	int		changeCount = 0 ;
	char		name2[MAXPATHLEN] ;
	int		apnd = 0 ;
	int		f0,f1,f2,f3 ;

	/* TODO: if absolute path, do we want to allow it?
	 * if relative path, do we want to prepend something?
	 */

	if( *name == '/' )	/* for now, disallow absolute paths */
	  return NULL ;

	if( stat(name, &buf) == 0 )
	  exists = 1 ;
	else if( errno == ENOENT )
	  exists = 0 ;
	else
	  return NULL ;


	/* if remote end has not specified transfer flags, we can
	 * accept the local definitions
	 */

	if( f0 == ZCRESUM ) {	/* if exists, and we already have it, return */
	  if( exists  &&  buf.st_size == info->len )
	    return NULL ;
	  apnd = 1 ;
	}

	/* reject if file not found and it most be there (ZMSKNOLOC) */
	if( !exists && (f1 & ZMSKNOLOC) )
	  return NULL ;

	switch( f1 & ZMMASK ) {
	  case 0:	/* Implementation-dependent.  In this case, we
			 * reject if file exists (and ZMSKNOLOC not set) */
	    if( exists && !(f1 & ZMSKNOLOC) )
	      return NULL ;
	    break ;

	  case ZMNEWL:	/* take if newer or longer than file on disk */
	    if( exists  &&  info->date <= buf.st_mtime  &&
		info->len <= buf.st_size )
	      return NULL ;
	    break ;

	  case ZMCRC:		/* take if different CRC or length */
	    if( exists  &&  info->len == buf.st_size && crc == FileCrc(name) )
	      return NULL ;
	    break ;

	  case ZMAPND:	/* append */
	    apnd = 1 ;
	  case ZMCLOB:	/* unconditional replace */
	    break ;

	  case ZMNEW:	/* take if newer than file on disk */
	    if( exists  &&  info->date <= buf.st_mtime )
	      return NULL ;
	    break ;

	  case ZMDIFF:	/* take if different date or length */
	    if( exists  &&  info->date == buf.st_mtime  &&
		info->len == buf.st_size )
	      return NULL ;
	    break ;

	  case ZMPROT:	/* only if dest does not exist */
	    if( exists )
	      return NULL ;
	    break ;

	  case ZMCHNG:	/* invent new filename if exists */
	    if( exists ) {
	      while( exists ) {
		sprintf(name2, "%s_%d", name, changeCount++) ;
		exists = stat(name2, &buf) == 0 || errno != ENOENT ;
	      }
	      name = name2 ;
	    }
	    break ;
	}

	/* here if we've decided to accept */
	if( exists && !apnd && unlink(name) != 0 )
	  return NULL ;

	/* TODO: build directory path if needed */

	return fopen(name, apnd ? "a" : "w") ;
}


int
ZWriteFile(buffer, len, file, info)
	u_char	*buffer ;
	int	len ;
	FILE	*file ;
	ZModem	*info ;
{
	/* TODO: if ZCNL set in info->f0, convert
	 * newlines to local convention
	 */

	return fwrite(buffer, 1, len, file) == len ? 0 : ZmErrSys ;
}


int
ZCloseFile(info)
	ZModem *info ;
{
	fclose(info->file) ;
	chmod(info->filename, info->mode&0777) ;
}
